package ace.module.account.core.impl.manager.impl;

import ace.cmp.core.constants.CoreConstant;
import ace.cmp.core.utils.SystemClockUtils;
import ace.cmp.i18n.api.MessageSourceAssertService;
import ace.module.account.api.model.dto.IamAccountPasswordDto;
import ace.module.account.core.impl.dao.entity.IamAccount;
import ace.module.account.core.impl.dao.entity.IamAccountPassport;
import ace.module.account.core.impl.dao.entity.IamAccountPassword;
import ace.module.account.core.impl.dao.repository.IamAccountPassportRepository;
import ace.module.account.core.impl.dao.repository.IamAccountPasswordRepository;
import ace.module.account.core.impl.manager.IamAccountPasswordManager;
import ace.module.common.core.impl.manager.impl.AbstractEntityOfAppManager;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author caspar
 * @date 2023/3/20 9:28
 */
@AllArgsConstructor
@Component
public class IamAccountPasswordManagerImpl
    extends AbstractEntityOfAppManager<IamAccountPassword, Long, IamAccountPasswordDto>
    implements IamAccountPasswordManager {

  private final IamAccountPassportRepository iamAccountPassportRepository;
  private final IamAccountPasswordRepository iamAccountPasswordRepository;
  private final MessageSourceAssertService assertService;
  private final PasswordEncoder passwordEncoder;

  @Override
  public List<IamAccountPassword> getByIamAppIdAndPassportAndPassportTypes(
      Long iamAppId, String passport, List<Integer> passportTypes) {

    List<IamAccountPassport> accountPassports = iamAccountPassportRepository
        .getByIamAppIdAndPassportAndPassportTypeInAndDeleteFlag(
            iamAppId,
            passport,
            passportTypes,
            CoreConstant.DELETE_FLAG_NOT
        );

    if (CollectionUtils.isEmpty(accountPassports)) {
      return new ArrayList<>();
    }

    List<Long> accountIds = accountPassports.stream().map(p -> p.getIamAccountId()).collect(Collectors.toList());

    List<IamAccountPassword> accountPasswordList = iamAccountPasswordRepository.getByIamAccountIdIn(accountIds);

    return accountPasswordList;
  }

  @Override
  public List<IamAccountPassword> getByIamAppIdAndTagAndPassportAndPassportTypes(
      Long iamAppId, String tag, String passport, List<Integer> passportTypes) {

    List<IamAccountPassport> accountPassports = iamAccountPassportRepository.getByIamAppIdAndPassportAndPassportTypeInAndDeleteFlag(
        iamAppId, passport, passportTypes, CoreConstant.DELETE_FLAG_NOT);

    if (CollectionUtils.isEmpty(accountPassports)) {
      return new ArrayList<>();
    }

    List<Long> accountIds =
        accountPassports.stream().map(p -> p.getIamAccountId()).collect(Collectors.toList());

    List<IamAccountPassword> accountPasswordList = iamAccountPasswordRepository.getByIamAccountIdIn(accountIds);

    return accountPasswordList;
  }

  @Override
  public IamAccountPassword getByIamAppIdAndPassportAndPassportType(
      Long iamAppId, String passport, Integer passportType) {

    IamAccountPassport iamAccountPassport = iamAccountPassportRepository.getByIamAppIdAndPassportAndPassportTypeAndDeleteFlag(
        iamAppId, passport, passportType, CoreConstant.DELETE_FLAG_NOT);

    if (iamAccountPassport == null) {
      return null;
    }

    return iamAccountPasswordRepository.getByIamAccountId(iamAccountPassport.getIamAccountId());
  }

  @Override
  public IamAccountPassword getAndCheckAllById(Long accountId) {
    IamAccountPassword iamAccountPassword = iamAccountPasswordRepository.getByIamAccountId(accountId);
    assertService.isNull(iamAccountPassword, "account.password.error-is-null", "密码数据不存在");
    assertService.isFalse(
        iamAccountPassword.getDeleteFlag().equals(CoreConstant.DELETE_FLAG_NOT),
        "account.password.error-is-null",
        "密码数据不存在");
    return iamAccountPassword;
  }

  @Override
  public List<IamAccountPassword> getByAccountIdIn(List<Long> iamAccountIds) {
    return iamAccountPasswordRepository.getByIamAccountIdIn(iamAccountIds);
  }

  @Override
  public IamAccountPassword build(Long accountId, Long iamAppId, String password) {
    String encodePassword = this.passwordEncoder.encode(password);
    return IamAccountPassword.builder()
        .id(this.getNewId())
        .iamAppId(iamAppId)
        .iamAccountId(accountId)
        .password(encodePassword)
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(SystemClockUtils.currentTimeMillis())
        .updateTime(SystemClockUtils.currentTimeMillis())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();
  }

  @Override
  public String encodePassword(String password) {
    return this.passwordEncoder.encode(password);
  }

  /**
   * 添加或修改如果有密码参数.
   *
   * @param iamAccount 基本账户
   * @param password 原始密码
   */
  @Transactional(rollbackFor = Throwable.class)
  @Override
  public void addOrModifyIfPasswordIsNotEmpty(IamAccount iamAccount, String password) {

    if (StringUtils.isBlank(password)) {
      return;
    }
    IamAccountPassword iamAccountPasswordOld = this.getByIamAccountIdAndDeleteFlagIsFalse(iamAccount.getId());

    IamAccountPassword iamAccountPassword = iamAccountPasswordOld;

    if (iamAccountPassword == null) {
      iamAccountPassword = this.build(iamAccount.getId(), iamAccount.getIamAppId(), password);
    }
    String encodePassword = this.encodePassword(password);
    iamAccountPassword.setPassword(encodePassword);
    this.save(iamAccountPassword);
  }

  public IamAccountPassword getByIamAccountIdAndDeleteFlagIsFalse(Long iamAccountId) {
    return this.iamAccountPasswordRepository.getByIamAccountIdAndDeleteFlagIsFalse(iamAccountId, CoreConstant.DELETE_FLAG_NOT);
  }
}
